﻿using System;
using System.Reflection;
using System.Collections.Generic;

namespace UFrameWork
{
    /// <summary>
    /// 框架
    /// </summary>
    public static class UWork
    {
        /// <summary>
        /// 命令关系表
        /// </summary>
        private static Dictionary<string, UMethod> map = new Dictionary<string, UMethod>();

        /// <summary>
        /// 注册类实例
        /// </summary>
        /// <param name="obj">实例对象</param>
        /// <param name="isType">是否为Type类型注册</param>
        public static void RegClass(object obj,bool isType = false)
        {
            Type oType = obj.GetType();
            if (isType) oType = (Type)obj;
            int order           = 0;
            string key          = string.Empty;
            object instance     = obj;
            bool isController   = oType.IsSubclassOf(typeof(UController));

            if (isController)
            {
                instance = oType.Assembly.CreateInstance(oType.FullName);
            }

            MethodInfo[] methods = oType.GetMethods();

            object[] atts = null;

            foreach (MethodInfo m in methods)
            {
                if(isController)
                {
                    atts = m.GetCustomAttributes(typeof(UControllerAction), false);
                    if (atts == null || atts.Length == 0) continue;
                    UControllerAction action = (UControllerAction)atts[0];
                    key     = action.Name;
                    order   = action.Order;
                }

                if (map.ContainsKey(key))
                {
                    map[key].Add(instance,m,order);
                }
                else
                {
                    map[key] = new UMethod(key,instance, m,order);
                }
            }
        }

        /// <summary>
        /// 注销类
        /// </summary>
        public static void UnRegClass(object obj)
        {
            foreach (UMethod v in map.Values)
            {
                if (v != null) v.Remove(obj);
            }
        }

        /// <summary>
        /// 注册程序集
        /// </summary>
        /// <param name="assembly">程序集</param>
        public static void RegAssembly(Assembly assembly)
        {
            Type[] types = assembly.GetExportedTypes();

            foreach (Type type in types)
            {
                if (!type.IsSubclassOf(typeof(UController)))
                    continue;
                RegClass(type,true);
            }
        }

        /// <summary>
        /// 更新程序集
        /// </summary>
        public static void UpdateAssembly(Assembly assembly)
        {
            foreach (UMethod v in map.Values)
            {
                v.Update(assembly);
            }
            RegAssembly(assembly);
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="key">命令名称</param>
        /// <param name="objs">参数列表</param>
        /// <returns></returns>
        public static void Do(string key, params object[] objs)
        {
            Invoke(key, objs);
        }

        /// <summary>
        /// 执行命令并返回结果
        /// </summary>
        /// <typeparam name="T">返回数据类型</typeparam>
        /// <param name="key">命令名称</param>
        /// <param name="objs">参数列表</param>
        /// <returns></returns>
        public static T Do<T>(string key, params object[] objs)
        {
            return (T)Invoke(key, objs);
        }

        /// <summary>
        /// 执行方法
        /// </summary>
        /// <param name="key">命令</param>
        /// <param name="objs">参数</param>
        /// <returns></returns>
        private static object Invoke(string key, object[] objs)
        {
            if (map.ContainsKey(key))
            {
                try
                {
                    return map[key].Invoke(objs);
                }
                catch (Exception e)
                {
                    UWork.Do(UEvent.CMD_DO_ERROR,map[key], objs, e);
                    ULog.Error(e);
                }
            }
            return null;
        }

        /// <summary>
        /// 获取方法的参数类型类别
        /// </summary>
        /// <returns></returns>
        public static List<Type> GetMethodParamType(string key)
        {
            if (!map.ContainsKey(key))
            {
                return null;
            }
            return map[key].GetMethodParamType();
        }
    }
}